/**
 * File: population.h
 *
 * Integrantes:
 * @author Jormar Arellano   (05-37840) <jormar.arellano@gmail.com>
 * @author Sabrina Fernández (05-38163) <sabrinamfm@gmail.com>
 */

#ifndef POPULATION_H
#define POPULATION_H

#include "arraylist.h"

#ifdef _cplusplus
extern "C" {
#endif

/** Definimos un cromosoma */
typedef struct {
	int used;				// Indica si ya fue usada para algun cruce.
    double rank;			// Clasificacion del cromosoma.
    ArrayList *colors;		// Vertices de colores.
} Chromosome;

/** Definimos una poblacion */
typedef struct {
	Chromosome *better;		// Mejor cromosoma encontrado.
    ArrayList *chrom;		// Lista de cromosomas que forman parte de la poblacion.
} Population;

/*
 * Reserva espacio para un nuevo cromosoma.
 * @return	Un nuevo cromosoma.
 */
Chromosome *newChromosome();

/*
 * Clona un cromosoma.
 * @param	chrom	El cromosoma a clonar.
 * @return	Un nuevo cromosoma copia del original.
 */
Chromosome *cloneChromosome(const Chromosome *chrom);

/*
 * Libera memoria del cromosoma.
 * @param	chrom	Cromosoma a borrar.
 */
void freeChromosome(Chromosome *chrom);

/*
 * Imprime un cromosoma
 * @param	chrom	Cromosoma que se va a imprimir.
 */
void printChromosome(Chromosome *chrom);

/**
 * Crea una lista de numeros aleatorios del rango [1..n]
 * @param   n   Tamaño del arreglo.
 * @return  Un arreglo de tamaño n de numeros aleatorios.
 */
ArrayList *newChromosomeArray(int n);

/*
 * Clona una poblacion
 * @param	pop	Poblacion que se va a clonar.
 * @return	Una poblacion igual a la principal.
 */
Population *clonePopulation(Population *pop);

/*
 * Reserva un espacio para la nueva poblacion.
 * @param	n	Tamaño de la poblacion.
 * @return	Una nueva poblacion.
 */
Population *newPopulation(int n);

/*
 * Libera memoria de la poblacion.
 * @param	pop		Poblacion a liberar.
 */
void freePopulation(Population *pop);

/*
 * Se imprime una poblacion.
 */
void printPopulation(Population *pop);

/*
 * Imprime una lista de cromosomas.
 */
void printChromList(ArrayList *list);

/*
 * Encuentra el mejor cromosoma para guardarlo posteriormente.
 * @param	pop	Poblacion que contiene el mejor cromosoma.
 * @return	El mejor cromosoma encontrado en la poblacion.
 */
Chromosome *findBetter(Population *pop);

/*
 * Hace cruce de un punto de dos cromosomas.
 * @param	chrom1		Primer cromosoma a clonar.
 * @param	chrom2		Segundo cromosoma a clonar.
 * @param	firstPoint	Punto a partir del cual se hara la clonacion.
 * @return	Una lista con el cruce de dos cromosomas.
 */
ArrayList *crossoverOnePoint(ArrayList *list, int firstPoint);

/*
 * Hace cruce de un punto de dos cromosomas.
 * @param	chrom1		Primer cromosoma a clonar.
 * @param	chrom2		Segundo cromosoma a clonar.
 * @param	firstPoint	Punto a partir del cual se hara la clonacion.
 * @param	secondPoint	Segundo punto a partir del cual no se clonara mas.
 * @return	Una lista con el cruce de dos cromosomas.
 */
ArrayList *crossoverTwoPoint(ArrayList *list, int firstPoint, int secondPoint);

/*
 * Realiza una mutacion k veces.
 * @param	chrom	Primer cromosoma a clonar.
 * @param	k		Cantidad de intercambios que se realizaran.
 */
ArrayList *mutationKSwap(ArrayList *list, int k);

/*
 * Cuenta la cantidad de colores en un cromosoma.
 * @param	list	Cromosoma al cual se le contaran los colores.
 * @return	El numero de colores diferentes que tiene el cromosoma.
 */
int countColors(ArrayList *list);

/*
 * Arregla un poblacion.
 * @param	pop		Poblacion que se volvera factible.
 */
Population *fixPopulation(Population *pop);

/*
 * Vuelve factible una poblacion a partir de un grafo.
 * @param	pop		Poblacion que se volvera factible.
 * @param	graph	Grafo de referencia.
 */
Population *makeFeasible(Population *pop, Graph *graph);

#ifdef _cplusplus
}
#endif

#endif
